#ifndef EE8216F1_F225_4811_93EE_6BF83D110584
#define EE8216F1_F225_4811_93EE_6BF83D110584


#endif /* EE8216F1_F225_4811_93EE_6BF83D110584 */

#include <iostream>
#include <queue>
#include <unistd.h>
#include <pthread.h>
using namespace std;

template<class T>
class BlockQueue
{
    static const int defaultnum = 20;       // 最大存储空间30个
public:
    BlockQueue(int maxcap = defaultnum)
        :_maxcap(maxcap)
    {
        pthread_mutex_init(&_mutex, nullptr);    // 初始化 该锁
        pthread_cond_init(&c_cond, nullptr);     // 初始化 消费者条件变量
        pthread_cond_init(&p_cond, nullptr);     // 初始化 生产者条件变量

        low_water = defaultnum/3;
        high_water = (defaultnum * 2)/3;
    }

    // 消费者
    T pop()
    {
        pthread_mutex_lock(&_mutex);
        while (_q.size() == 0)
        {
            pthread_cond_wait(&c_cond, &_mutex);
        }
        
        T ret = _q.front();
        _q.pop();

        if(_q.size() < low_water)
            pthread_cond_signal(&p_cond);
        //pthread_cond_signal(&p_cond);
        pthread_mutex_unlock(&_mutex);
        return ret;
    }

    // 生产者
    void push(const T& data)
    {
        pthread_mutex_lock(&_mutex);
        while(_q.size() == _maxcap)
        {
            pthread_cond_wait(&p_cond, &_mutex);
        }
        _q.push(data);

        if(_q.size() > high_water) 
            pthread_cond_signal(&c_cond);
        // pthread_cond_signal(&c_cond);
        pthread_mutex_unlock(&_mutex);
    }
    
    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&c_cond);
        pthread_cond_destroy(&p_cond);
    }
private:
    queue<T> _q;
    int _maxcap;        // 极值
    pthread_mutex_t _mutex; //一个锁
    pthread_cond_t c_cond;  // 消费者条件变量
    pthread_cond_t p_cond;  // 生产者条件变量

    int low_water;
    int high_water;
};
